package com.bzframework.pro.api.core.provider;

import lombok.NonNull;
import lombok.SneakyThrows;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Author bingzhong
 * @Date 2025/2/28 11:31
 * @Description api支持管理
 */
public class ApiSupportManager {

    private static final List<ApiSupport> apiSupports = new CopyOnWriteArrayList<>();

    public void register(ApiSupport apiSupport) {
        apiSupports.add(apiSupport);
    }

    public List<ApiSupport> getApiSupports() {
        return apiSupports;
    }

    @SneakyThrows
    public void loadJar(String location) {
        location = String.format("jar:file:%s!/**/*.class", location);

        PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver() {
            @Override
            protected boolean isJarResource(@NonNull Resource resource) {
                return true;
            }
        };
        CachingMetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory();
        Resource[] classes = resourcePatternResolver.getResources(location);
        List<MetadataReader> classResources = new ArrayList<>(classes.length);
        for (Resource aClass : classes) {
            classResources.add(metadataReaderFactory.getMetadataReader(aClass));
        }
        URL url = new File(location).toURI().toURL();
        URLClassLoader classLoader = new URLClassLoader(
                new URL[]{url},
                // 使用当前线程的类加载器作为父类加载器
                Thread.currentThread().getContextClassLoader()
        );
        List<ApiSupport> apiSupports = new ArrayList<>();
        for (MetadataReader metadataReader : classResources) {
            String className = metadataReader.getClassMetadata().getClassName();
            Class<?> aClass = classLoader.loadClass(className);
            if (!ApiSupportProvider.class.isAssignableFrom(aClass) || aClass.isInterface()) {
                continue;
            }
            ApiSupportProvider apiSupportProvider = (ApiSupportProvider) aClass.getDeclaredConstructor().newInstance();
            apiSupports.addAll(apiSupportProvider.create());
        }
        apiSupports.forEach(this::register);
        metadataReaderFactory.clearCache();
        classLoader.close();
    }

}
